{-# OPTIONS_GHC -Wall -Werror -fno-warn-orphans #-}
{-# LANGUAGE FlexibleContexts, TypeFamilies, 
  FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances #-}

module Vector3D where

import Data.VectorSpace hiding (Scalar)
import qualified Data.VectorSpace as VS

import Math
import Projectable
import Control.Parallel.Strategies

data Vector3 = V3 !Scalar !Scalar !Scalar deriving (Show,Eq,Read)

-- | Construct a 3D vector
vector3 :: Scalar -> Scalar -> Scalar -> Vector3
vector3 = V3

{-# INLINE vector3 #-} 

instance Project3 Vector3 where
  project3 (V3 x y z) = (x,y,z)
  compose3 (x,y,z) = (V3 x y z)

instance ProjectX Vector3 where
  getX (V3 x _ _) = x
  mapX f (V3 x y z) = V3 (f x) y z

instance ProjectY Vector3 where
  getY (V3 _ y _) = y
  mapY f (V3 x y z) = V3 x (f y) z

instance ProjectZ Vector3 where
  getZ (V3 _ _ z) = z
  mapZ f (V3 x y z) = V3 x y (f z)

instance AdditiveGroup Vector3 where
  zeroV = V3 0 0 0
  V3 x1 y1 z1 ^+^ V3 x2 y2 z2 = V3 (x1+x2) (y1+y2) (z1+z2)
  negateV (V3 x y z) = V3 (negate x) (negate y) (negate z)

instance VectorSpace Vector3 where
  type VS.Scalar (Vector3) = Scalar
  s *^ V3 x y z = V3 (s*x) (s*y) (s*z)

instance InnerSpace Vector3 where
  V3 x1 y1 z1 <.> V3 x2 y2 z2 = x1*x2+y1*y2+z1*z2

instance NFData (Vector3)


 
